/*
 * Copyright (C) 2025 Tsingteng MicroSystem
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * @file nfa_rw_t5t.c
 * @brief T5T tag api implementation
 */

#include "nci_feature.h"

#if IS_FEATURE_ON(NCI_FEATURE_RW_T5T)

#include "rw_t5t_common.h"
#include "nci_defs.h"
#include "nfa_rw_t5t.h"
#include "nfa_rw.h"
#include "nci_utils.h"

tNCI_STATUS nfa_rw_i93_read_single_block(uint16_t block_number, tNCI_RSP *p_rsp)
{
    if (!p_rsp) {
        NFCLOG_E("invalid param");
        return NCI_STATUS_EXT_INVALID_PARAM;
    }

    tNCI_STATUS status = nfa_rw_request_lock();
    if (status != NCI_STATUS_OK) {
        NFCLOG_E("nfa_rw_request_lock failed, ret=%d", status);
        return status;
    }
    tNCI_BUF *rsp = alloc_nci_buf(0);
    if (!rsp) {
        NFCLOG_E("alloc nci buf failed");
        status = NCI_STATUS_EXT_ALLOC_FAILED;
        goto exit;
    }
    NFCLOG_D("enter");

    status = rw_i93_send_cmd_read_single_block(block_number, false, rsp);
    if (status != NCI_STATUS_OK) {
        NFCLOG_E("read block %d failed", block_number);
        goto exit;
    }
    p_rsp->data = rsp->data;
    p_rsp->len = rsp->len;
    rsp->data = NULL;
    rsp->len = 0;

exit:
    nfa_rw_release_lock();
    free_nci_buf(rsp);
    if (status != NCI_STATUS_OK) {
        nfa_utils_free_rsp(p_rsp, true);
    }
    NFCLOG_D("exit");
    return status;
}

tNCI_STATUS nfa_rw_i93_inventory(uint8_t* p_uid, bool including_afi, uint8_t afi)
{
    tNCI_STATUS ret = nfa_rw_request_lock();
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("nfa_rw_request_lock failed, ret=%d", ret);
        return ret;
    }
    ret = rw_i93_send_cmd_inventory(p_uid, including_afi, afi);
    nfa_rw_release_lock();

    return ret;
}

tNCI_STATUS nfa_rw_i93_select(const uint8_t* p_uid)
{
    tT5T_INFO *p_i93 = &s_t5t_info;
    tNCI_STATUS ret = nfa_rw_request_lock();
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("nfa_rw_request_lock failed, ret=%d", ret);
        return ret;
    }
    ret = rw_i93_send_cmd_select(p_uid);
    if (ret == NCI_STATUS_OK) {
        NFCLOG_I("send_cmd_select ok");
        p_i93->addr_mode = RW_I93_MODE_NON_ADDRESSED;
        p_i93->intl_flags |= RW_I93_FLAG_SELECTED_STATE;
    }
    nfa_rw_release_lock();

    return ret;
}

tNCI_STATUS nfa_rw_i93_stay_quiet(const uint8_t* p_uid)
{
    tT5T_INFO *p_i93 = &s_t5t_info;
    tNCI_STATUS ret = nfa_rw_request_lock();
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("nfa_rw_request_lock failed, ret=%d", ret);
        return ret;
    }
    ret = rw_i93_send_cmd_stay_quiet(p_uid);
    if (ret == NCI_STATUS_OK) {
        NFCLOG_I("send_cmd_stay_quiet ok");
        p_i93->addr_mode = RW_I93_MODE_ADDRESSED;
    }
    nfa_rw_release_lock();

    return ret;
}

void nfa_rw_i93_set_addressing_mode(bool mode)
{
    tNCI_STATUS ret = nfa_rw_request_lock();
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("nfa_rw_request_lock failed, ret=%d", ret);
        return ;
    }
    rw_i93_send_cmd_set_addressing_mode(mode);
    nfa_rw_release_lock();
    return ;
}

#if IS_FEATURE_ON(NCI_FEATURE_RW_NDEF)

tNCI_STATUS nfa_rw_i93_read_multi_blocks(uint16_t first_block_number, uint16_t number_blocks, tNCI_RSP *p_rsp)
{
    if (!p_rsp) {
        NFCLOG_E("invalid param");
        return NCI_STATUS_EXT_INVALID_PARAM;
    }

    tNCI_STATUS status = nfa_rw_request_lock();
    if (status != NCI_STATUS_OK) {
        NFCLOG_E("nfa_rw_request_lock failed, ret=%d", status);
        return status;
    }
    tNCI_BUF *rsp = alloc_nci_buf(0);
    NFCLOG_D("enter");

    status = rw_i93_send_cmd_read_multi_blocks(first_block_number, number_blocks, rsp);
    if (status != NCI_STATUS_OK) {
        NFCLOG_E("read multi block %d, %d failed", first_block_number, number_blocks);
        goto exit;
    }
    p_rsp->data = rsp->data;
    p_rsp->len = rsp->len;
    rsp->data = NULL;
    rsp->len = 0;

exit:
    nfa_rw_release_lock();
    free_nci_buf(rsp);
    if (status != NCI_STATUS_OK) {
        nfa_utils_free_rsp(p_rsp, true);
    }
    NFCLOG_D("exit");
    return status;
}

tNCI_STATUS nfa_rw_i93_write_single_block(uint32_t block_number,  uint8_t* p_data)
{
    tNCI_STATUS ret = nfa_rw_request_lock();
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("nfa_rw_request_lock failed, ret=%d", ret);
        return ret;
    }
    ret = rw_i93_send_cmd_write_single_block(block_number, p_data);
    nfa_rw_release_lock();

    return ret;
}

tNCI_STATUS nfa_rw_i93_lock_block(uint32_t block_number)
{
    tNCI_STATUS ret = nfa_rw_request_lock();
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("nfa_rw_request_lock failed, ret=%d", ret);
        return ret;
    }
    ret = rw_i93_send_cmd_lock_block(block_number);
    nfa_rw_release_lock();

    return ret;
}

#endif // IS_FEATURE_ON(NCI_FEATURE_RW_NDEF)
#endif //IS_FEATURE_ON(NCI_FEATURE_RW_T5T)